package com.stronglink.esm27.datasync.service;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import com.stronglink.esm27.common.FtpUtils;
import com.stronglink.esm27.datasync.entity.SyncDataEntity;
import com.stronglink.esm27.datasync.entity.SyncTableEntity;
import com.stronglink.esm27.datasync.entity.SyncTableStructureEntity;
import com.stronglink.esm27.datasync.exception.InsertDataFailException;
import com.stronglink.esm27.datasync.exception.NoMatchingTableException;
import com.stronglink.esm27.datasync.exception.UpdateDataFailException;

/**
 * @author yuzhantao
 *
 */
@Service("dataSyncService")
public class DataSyncService implements IDataSyncService {

	/**
	 * 中心同步数据到本地模式
	 */
	public final static String CENTER_TO_LOCAL_SYNC_MODE = "centerToLocal";

	/**
	 * 本地数据同步到中心模式
	 */
	public final static String LOCAL_TO_CENTER_SYNC_MODE = "localToCenter";
	/**
	 * 双向同步模式
	 */
	public final static String DOUBLE_SYNC_MODE = "double";

	Logger logger = LogManager.getLogger(this.getClass());
	final static String CONFIG_TABLE_NAME = "sync_config";
	private SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	@Autowired
	SyncConfigRepository syncConfigRepository;

	@Override
	public int insert(String destConnectionParams, String table, List<Map<String, Object>> srcDatas,
			ISQLListener listener) throws SQLException {
		insertDataToDestTable(srcDatas, destConnectionParams, table, "", listener);

		return 0;
	}

	@Override
	public List<Map<String, Object>> getTableAllContent(String srcConnectionParams, String table) throws SQLException {
		List<Map<String, Object>> tableDataList = new ArrayList<>();
		Connection conn = DriverManager.getConnection(srcConnectionParams);
		Statement statement = conn.createStatement();
		ResultSet results = statement.executeQuery("SELECT * FROM " + table);
		ResultSetMetaData metadata = results.getMetaData();
		int columnCount = metadata.getColumnCount();
		while (results.next()) {
			Map<String, Object> rowMap = new HashMap<>();
			for (int i = 1; i <= columnCount; i++) {
				String columnName = metadata.getColumnName(i);
				rowMap.put(columnName, results.getObject(i));
			}
			tableDataList.add(rowMap);
		}
		conn.close();
		return tableDataList;
	}

	@Override
	public int clearTableContent(String srcConnectionParams, String table) throws SQLException {
		Connection conn = DriverManager.getConnection(srcConnectionParams);
		Statement statement = conn.createStatement();
		int delCount = statement.executeUpdate("DELETE FROM " + table);
		return delCount;
	}

	@Override
	public void syncTable(SyncDataEntity syncData, String srcTable, String destTable, Set<String> feildSet,
			SyncTableEntity syncTableParams) throws SQLException, ClassNotFoundException {
		Preconditions.checkNotNull(feildSet, "表格字段为空");
		Preconditions.checkArgument(feildSet.size() > 0, "表格字段为0");

		String srcConnectionParams = syncData.getSrcDataSourceParams();
		String destConnectionParams = syncData.getDestDataSourceParams();

		switch (syncData.getSyncMode()) {
		case CENTER_TO_LOCAL_SYNC_MODE: // 单项同步模式
			syncDataToDestTable(syncData, srcConnectionParams, srcTable, destConnectionParams, destTable, feildSet,
					syncTableParams);
			break;
		case LOCAL_TO_CENTER_SYNC_MODE:
			syncDataToDestTable(syncData, destConnectionParams, srcTable, srcConnectionParams, destTable, feildSet,
					syncTableParams);
			break;
		default: // 默认双向同步模式
			List<Ids> ids = syncDataToDestTable(syncData, srcConnectionParams, srcTable, destConnectionParams,
					destTable, feildSet, syncTableParams);
			syncDataToScrTable(syncData, srcConnectionParams, srcTable, destConnectionParams, destTable, feildSet,
					syncTableParams, ids);
			break;
		}
	}

	private List<Ids> syncDataToDestTable(SyncDataEntity syncData, String srcConnectionParams, String srcTable,
			String destConnectionParams, String destTable, Set<String> feildSet, SyncTableEntity syncTableParams)
			throws SQLException, ClassNotFoundException {
		Preconditions.checkNotNull(feildSet);
		Preconditions.checkArgument(feildSet.size() > 0, "表格字段为0");

		String configId = (srcConnectionParams + destConnectionParams + srcTable + "_DOWN").toLowerCase();
		String prevSyncTime = getSyncTime(configId);

		// 获取源表中需要同步的数据
		List<Map<String, Object>> tableDataList = new ArrayList<>();
		Connection conn = DriverManager.getConnection(srcConnectionParams);
		Statement statement = conn.createStatement();
		String findSyncSql = "SELECT * FROM " + srcTable + " limit 0";
		ResultSet results = statement.executeQuery(findSyncSql);
		ResultSetMetaData metadata = results.getMetaData();
		StringBuffer sbSql = new StringBuffer();
		sbSql.append("SELECT ");
		for (int i = 1; i <= metadata.getColumnCount(); i++) {
			if (metadata.getColumnTypeName(i).equals("GEOMETRY")) {
				sbSql.append("astext(" + metadata.getColumnName(i) + ")");
			} else {
				sbSql.append(metadata.getColumnName(i));
			}
			if (i < metadata.getColumnCount()) {
				sbSql.append(",");
			}
		}
		sbSql.append(" FROM " + srcTable + " where " + syncTableParams.getSyncUpdateColumnName() + ">'" + prevSyncTime
				+ "'");
		logger.info("[SEL DB] " + sbSql.toString());
		results = statement.executeQuery(sbSql.toString());

		int columnCount = metadata.getColumnCount();
		while (results.next()) {
			Map<String, Object> rowMap = new HashMap<>();
			for (int i = 1; i <= columnCount; i++) {
				String columnName = metadata.getColumnName(i);
				if (feildSet.contains(columnName)) {
					rowMap.put(columnName, results.getObject(i));
				}
			}
			tableDataList.add(rowMap);
		}
		conn.close();
		if (tableDataList.size() == 0)
			return new ArrayList<Ids>();

		insertDataToDestTable(tableDataList, destConnectionParams, destTable, syncTableParams.getSyncUpdateColumnName(),
				null); // 插入数据到目标表
//		List<Ids> ids = updateSrcTableSyncTime(srcConnectionParams, srcTable, tableDataList,
//				syncTableParams.getSyncUpdateColumnName()); // 更新源表中的同步时间
		// 获取表中更新字段最大的时间值
//		conn = DriverManager.getConnection(destConnectionParams);
//		statement = conn.createStatement();
//		Date maxSyncTime = null;
//		String findMaxTimeSql = "select max(" + syncTableParams.getSyncUpdateColumnName() + ") from " + destTable;
//		logger.info("[Select DB] " + findMaxTimeSql);
//		ResultSet maxResults = statement.executeQuery(findMaxTimeSql);
//		while (maxResults.next()) {
//			maxSyncTime = maxResults.getDate(1);
//		}
//		conn.close();
		// 更新同步时间
		this.updateSyncTime(configId, new Date());

		if (syncTableParams.getSnycFileColumnNames() != null && syncTableParams.getSnycFileColumnNames().length > 0) {
			FtpUtils ftp = new FtpUtils();
			ftp.hostname = syncData.getSrcFtpHost();
			ftp.port = syncData.getSrcFtpPort();
			ftp.username = syncData.getSrcFtpLoginName();
			ftp.password = syncData.getSrcFtpLoginPassword();
			for (Map<String, Object> item : tableDataList) {
				for (String columnName : syncTableParams.getSnycFileColumnNames()) {
					if (!item.containsKey(columnName))
						continue;
					String path = (String) item.get(columnName);
					logger.info(columnName + ":" + path);
					if (path == null || path == "" || path.isEmpty())
						continue;

					int index = path.lastIndexOf("/");
					String srcPath = "";
					String srcFileName = "";
					if (index > -1) {
						srcPath = path.substring(0, index);
						srcFileName = path.substring(index + 1);
					}

					if (syncData.getSyncMode() != null && syncData.getSyncMode().equals(LOCAL_TO_CENTER_SYNC_MODE)) {
						String destPath = syncData.getDestPath() + path;
						ftp.uploadFile(srcPath, srcFileName, destPath);
					} else {
						String destPath = syncData.getDestPath() + srcPath;
						ftp.downloadFile(srcPath, srcFileName, destPath);
					}
				}
			}
		}

		List<Ids> ids = this.getIds(srcConnectionParams, srcTable, tableDataList,
				syncTableParams.getSyncUpdateColumnName());
		return ids;
	}

	/**
	 * 同步数据到源表中
	 * 
	 * @param srcConnectionParams
	 * @param srcTable
	 * @param destConnectionParams
	 * @param destTable
	 * @param feildSet
	 * @param syncColumnName
	 * @param updateIdMap
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	private void syncDataToScrTable(SyncDataEntity syncData, String srcConnectionParams, String srcTable,
			String destConnectionParams, String destTable, Set<String> feildSet, SyncTableEntity syncTableParams,
			List<Ids> updateIds) throws SQLException, ClassNotFoundException {
		Preconditions.checkNotNull(feildSet, "表格字段为空");
		Preconditions.checkArgument(feildSet.size() > 0, "表格字段为0");

		String configId = (srcConnectionParams + destConnectionParams + srcTable + "_UP").toLowerCase();
		String prevSyncTime = getSyncTime(configId);
		// 获取源表中需要同步的数据
		List<Map<String, Object>> tableDataList = new ArrayList<>();
		Connection conn = DriverManager.getConnection(destConnectionParams);
		Statement statement = conn.createStatement();
		String findSyncSql = "SELECT * FROM " + destTable + " limit 0";
		ResultSet results = statement.executeQuery(findSyncSql);
		ResultSetMetaData metadata = results.getMetaData();
		StringBuffer sbSql = new StringBuffer();
		sbSql.append("SELECT ");
		for (int i = 1; i <= metadata.getColumnCount(); i++) {
			if (metadata.getColumnTypeName(i).equals("GEOMETRY")) {
				sbSql.append("astext(" + metadata.getColumnName(i) + ")");
			} else {
				sbSql.append(metadata.getColumnName(i));
			}
			if (i < metadata.getColumnCount()) {
				sbSql.append(",");
			}
		}
		sbSql.append(" FROM " + destTable + " where " + syncTableParams.getSyncUpdateColumnName() + ">'" + prevSyncTime
				+ "'");
		logger.info("[SEL DB] " + sbSql.toString());
		results = statement.executeQuery(sbSql.toString());
		int columnCount = metadata.getColumnCount();

		while (results.next()) {
			Map<String, Object> rowMap = new HashMap<>();
			for (int i = 1; i <= columnCount; i++) {
				String columnName = metadata.getColumnName(i).toLowerCase();
				if (feildSet.contains(columnName)) {
					rowMap.put(columnName, results.getObject(i));
				}
			}
			tableDataList.add(rowMap);
		}

		conn.close();

		if (tableDataList.size() == 0) {
			// 如果查找到了最大值，将更新时间保存到本地H2库中
			updateSyncTime(configId, new Date()); // 更新同步时间
			return;
		}

		// 插入数据到目标表
		insertDataToDestTable(tableDataList, srcConnectionParams, srcTable, syncTableParams.getSyncUpdateColumnName(),
				null);

		// 如果查找到了最大值，将更新时间保存到本地H2库中
		updateSyncTime(configId, new Date()); // 更新同步时间

		if (syncTableParams.getSnycFileColumnNames() != null && syncTableParams.getSnycFileColumnNames().length > 0) {
			FtpUtils ftp = new FtpUtils();
			ftp.hostname = syncData.getSrcFtpHost();
			ftp.port = syncData.getSrcFtpPort();
			ftp.username = syncData.getSrcFtpLoginName();
			ftp.password = syncData.getSrcFtpLoginPassword();
			for (Map<String, Object> item : tableDataList) {
				for (String columnName : syncTableParams.getSnycFileColumnNames()) {
					if (!item.containsKey(columnName))
						continue;
					String path = (String) item.get(columnName);
					if (path == null || path.isEmpty())
						continue;

					int index = path.lastIndexOf("/");
					String srcPath = "";
					String srcFileName = "";
					if (index > -1) {
						srcPath = path.substring(0, index);
						srcFileName = path.substring(index + 1);
					}

					String destPath = syncData.getDestPath() + path;
					ftp.uploadFile(srcPath, srcFileName, destPath);
				}
			}
		}
	}

	private String getSyncTime(String id) throws ClassNotFoundException, SQLException {
		Class.forName("org.h2.Driver");
		Connection conn = null;
		try {
			conn = DriverManager.getConnection("jdbc:h2:./config;INIT=RUNSCRIPT FROM 'classpath:h2_init.sql'", "sa",
					"");
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery("SELECT SYNC_TIME FROM SYNC_CONFIG WHERE SYNC_ID='" + id + "'");
			while (rs.next()) {
				String syncTime = rs.getString("SYNC_TIME");
				return syncTime;
			}
			// 如果没有查到，则插入并返回1970年
			String sql = "INSERT INTO SYNC_CONFIG VALUES ('" + id + "', '2000-1-1');";

			int result = stmt.executeUpdate(sql);
			logger.info("[LOCAL SYNC_CONFIG]" + sql);
			if (result == 0) {
				throw new InsertDataFailException(sql);
			}
		} finally {
			if (conn != null) {
				conn.close();
			}
		}

		return "2000-1-1";
	}

	/**
	 * 更新同步时间
	 * 
	 * @param id
	 * @param syncDate
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	private void updateSyncTime(String id, Date syncDate) throws SQLException, ClassNotFoundException {
		Class.forName("org.h2.Driver");
		Connection conn = null;
		try {
			conn = DriverManager.getConnection("jdbc:h2:./config;INIT=RUNSCRIPT FROM 'classpath:h2_init.sql'", "sa",
					"");
			Statement stmt = conn.createStatement();

			String strDate = sDateFormat.format(syncDate);
			String sql = "UPDATE SYNC_CONFIG SET SYNC_TIME = '" + strDate + "' WHERE SYNC_ID = '" + id + "'";
			int result = stmt.executeUpdate(sql);
			logger.info("[LOCAL SYNC_CONFIG]" + sql);
			if (result == 0) {
				throw new UpdateDataFailException(sql);
			}
		} finally {
			if (conn != null) {
				conn.close();
			}
		}
	}

	/**
	 * 插入数据到目标表
	 * 
	 * @param srcTableDatas
	 * @param destConnectionParams
	 * @param destTable
	 * @throws SQLException
	 */
	private void insertDataToDestTable(List<Map<String, Object>> srcTableDatas, String destConnectionParams,
			String destTable, String syncColumnName, ISQLListener listener) throws SQLException {
		if (srcTableDatas == null || srcTableDatas.size() == 0)
			return;
		Connection conn = DriverManager.getConnection(destConnectionParams);
		try {
			Statement statement = conn.createStatement();
			if (listener != null) {
				listener.onConnectioned();
			}
			conn.setAutoCommit(false); // 禁止JDBC自动提交事务
			// 遍历所有从源数据表读取的数据，并插入到目标表中
			for (int i = 0; i < srcTableDatas.size(); i++) {
				String sql = this.mapToInsertSql(destTable, syncColumnName, srcTableDatas.get(i)); // 将map里的数据转为插入的sql
				logger.info("[TO DEST] " + sql);
				int results = statement.executeUpdate(sql);
				if (listener != null) {
					listener.onExecuteUpdate(destTable, sql, results);
				}
				if (results == 0) {
					throw new InsertDataFailException(sql.toString());
				}
			}
			conn.commit();
		} catch (Exception e) {
			try {
				conn.rollback(); // 数据回滚
			} catch (Exception connErr) {
				connErr.printStackTrace();
			}
			if (listener != null) {
				listener.onError(e);
			}
			throw e;
		} finally {
			conn.close();
			if (listener != null) {
				listener.onClose();
			}
		}
	}

	/**
	 * 获取指定数据的Id数组
	 * 
	 * @param srcConnectionParams
	 * @param tableName
	 * @param srcTableDatas
	 * @param syncColumnName
	 * @return
	 * @throws SQLException
	 */
	private List<Ids> getIds(String srcConnectionParams, String tableName, List<Map<String, Object>> srcTableDatas,
			String syncColumnName) throws SQLException {
		List<Ids> ids = new ArrayList<>();
		Connection conn = DriverManager.getConnection(srcConnectionParams);
		try {
			DatabaseMetaData dbMeta = conn.getMetaData();
			ResultSet pkRSet = dbMeta.getPrimaryKeys(null, null, tableName);
			String keyName = ""; // 表的主键名
			while (pkRSet.next()) {
				keyName = String.valueOf(pkRSet.getObject(4));
			}

			for (int i = 0; i < srcTableDatas.size(); i++) {
				ids.add(new Ids(keyName, String.valueOf(srcTableDatas.get(i).get(keyName))));
			}
		} finally {
			conn.close();
		}

		return ids;
	}

	/**
	 * 更新源表中的同步时间
	 * 
	 * @param srcConnectionParams
	 * @param tableName
	 * @param srcTableDatas
	 * @throws SQLException
	 */
//	private List<Ids> updateSrcTableSyncTime(String srcConnectionParams, String tableName,
//			List<Map<String, Object>> srcTableDatas, String syncColumnName) throws SQLException {
//		List<Ids> ids = new ArrayList<>();
//		Connection conn = DriverManager.getConnection(srcConnectionParams);
//		try {
//			DatabaseMetaData dbMeta = conn.getMetaData();
//			ResultSet pkRSet = dbMeta.getPrimaryKeys(null, null, tableName);
//			String keyName = ""; // 表的主键名
//			while (pkRSet.next()) {
//				keyName = String.valueOf(pkRSet.getObject(4));
//			}
//
//			String date = sDateFormat.format(new Date());
//
//			Statement statement = conn.createStatement();
//			conn.setAutoCommit(false); // 禁止JDBC自动提交事务
//			for (int i = 0; i < srcTableDatas.size(); i++) {
//				ids.add(new Ids(keyName, String.valueOf(srcTableDatas.get(i).get(keyName))));
//				StringBuffer sb = new StringBuffer("UPDATE " + tableName + " SET ");
//				sb.append(syncColumnName);
//				sb.append(" = '");
//				sb.append(date);
//				sb.append("' where ");
//				sb.append(keyName);
//				sb.append("='");
//				sb.append(String.valueOf(srcTableDatas.get(i).get(keyName)));
//				sb.append("'");
//				int result = statement.executeUpdate(sb.toString());
//				logger.info("[UPDATE SRC]" + sb.toString());
//				if (result == 0) {
//					throw new UpdateDataFailException(sb.toString());
//				}
//			}
//			conn.commit();
//		} catch (Exception e) {
//			try {
//				conn.rollback();
//			} catch (SQLException e1) {
//				e1.printStackTrace();
//			}
//			throw e;
//		} finally {
//			conn.close();
//		}
//
//		return ids;
//	}

	/**
	 * 将map里的数据转为插入sql语句
	 * 
	 * @param tableNme
	 * @param rowMap
	 * @return
	 */
	private String mapToInsertSql(String tableNme, String syncColumnName, Map<String, Object> rowMap) {
		String tempSyncColumnName = syncColumnName.toLowerCase();
		StringBuffer sql = new StringBuffer("REPLACE INTO " + tableNme + "("); // 插入数据的SQL语句
		// 遍历拼接插入的字段名
		for (String columnName : rowMap.keySet()) {
			sql.append(columnName);
			sql.append(",");
		}
		sql.deleteCharAt(sql.length() - 1); // 清除最后一个逗号
		sql.append(") values(");

		// 获取当前更新时间
		String date = "NOW()";
		// 遍历拼接字段值
		for (Map.Entry<String, Object> item : rowMap.entrySet()) {
			// 如果字段名等于同步的字段名，就更新当前时间；否则就按照源库数据拷贝
			if (tempSyncColumnName.equals(item.getKey().toLowerCase())) {
				sql.append(date);
				sql.append(",");
			} else if (item.getValue() instanceof Integer || item.getValue() instanceof Boolean) {
				sql.append(item.getValue());
				sql.append(",");
			} else if (item.getValue() == null) {
				sql.append("null,");
			} else {
				String strValue = item.getValue().toString().replaceAll("'", "\\\\\'");
				if (strValue.indexOf("POINT") == 0) {
					sql.append("geomfromtext(");
				}
				sql.append("'");
				sql.append(strValue);
				sql.append("'");
				// 如果内容前几个字母是“"POINT(”，代表字段存储的是经纬度格式，需要添加转换函数
				if (strValue.indexOf("POINT(") == 0) {
					sql.append(")");
				}
				sql.append(",");
			}
		}
		sql.deleteCharAt(sql.length() - 1); // 清除最后一个逗号
		sql.append(");");
		return sql.toString();
	}

	/**
	 * 获取同步表格的结构实体
	 * 
	 * @param srcDataSurceParams
	 * @param destDataSurecParams
	 * @param syncColumnName
	 * @return
	 * @throws SQLException 
	 */
	@Override
	public SyncTableStructureEntity getSyncTableStructure(String srcDataSurceParams, String destDataSurecParams,
			SyncTableEntity[] syncTables) throws SQLException {
		Map<String, Set<String>> srcTableStructure = null, destTableStructure = null;
		srcTableStructure = this.getTableStructure(srcDataSurceParams);
		destTableStructure = this.getTableStructure(destDataSurecParams);

		Set<String> srcMapKey = srcTableStructure.keySet();
		Set<String> destMapKey = destTableStructure.keySet();
		Set<String> syncTableNames = new HashSet<>();
		for (int i = 0; i < syncTables.length; i++) {
			SyncTableEntity tn = syncTables[i];
			syncTableNames.add(tn.getTableName());
		}
		Set<String> tempSet = Sets.intersection(srcMapKey, destMapKey); // 获取原始表和目标表的并集
		Set<String> intersectionSet = Sets.intersection(syncTableNames, tempSet); // 获取原始表和目标表的并集与需要同步数据表的并集
		Map<String, SyncTableEntity> syncTableMap = new HashMap<>();
		for (int i = 0; i < syncTables.length; i++) {
			SyncTableEntity tn = syncTables[i];
			syncTableMap.put(tn.getTableName(), tn);
		}
		if (intersectionSet.size() == 0) {
			throw new NoMatchingTableException();
		}

		Map<String, Set<String>> resultSrcTableStructure = new HashMap<>(), resultDestTableStructure = new HashMap<>();
		for (String tableName : intersectionSet) {
			SyncTableEntity table = syncTableMap.get(tableName);
			String tempSyncColumnName = table.getSyncUpdateColumnName().toLowerCase();
			for (String columnName : srcTableStructure.get(tableName)) {
				// 如果表里有同步的字段，才可以记到同步列表中
				if (columnName.toLowerCase().equals(tempSyncColumnName)) {
					resultSrcTableStructure.put(tableName, srcTableStructure.get(tableName));
					resultDestTableStructure.put(tableName, destTableStructure.get(tableName));
					break;
				}
			}
		}

		srcTableStructure.clear();
		destTableStructure.clear();

		SyncTableStructureEntity syncTableStructureEntity = new SyncTableStructureEntity();
		syncTableStructureEntity.setSrcTableStructure(resultSrcTableStructure);
		syncTableStructureEntity.setDestTableStructure(resultDestTableStructure);
		syncTableStructureEntity.setSyncTableParams(syncTableMap);
		return syncTableStructureEntity;
	}

	/**
	 * 获取表格结构
	 * 
	 * @param url
	 * @return
	 * @throws SQLException
	 */
	private Map<String, Set<String>> getTableStructure(String url) throws SQLException {
		Map<String, Set<String>> resultMap = new HashMap<>();
		Connection conn = DriverManager.getConnection(url);
		try {
			DatabaseMetaData md = conn.getMetaData();
			ResultSet rs = md.getTables(null, null, "%", null);
			while (rs.next()) {
				// 表名
				String tableName = rs.getString(3);
				Set<String> fieldSet = new HashSet<>();
				Statement statement = conn.createStatement();
				String sql = "SELECT * FROM " + tableName + " limit 0";
				ResultSet results = statement.executeQuery(sql);
				ResultSetMetaData metadata = results.getMetaData();
				int columnCount = metadata.getColumnCount();
				for (int i = 1; i <= columnCount; i++) {
					String columnName = metadata.getColumnName(i);
					fieldSet.add(columnName);
				}
				resultMap.put(tableName, fieldSet);
			}
		} finally {
			conn.close();
		}
		return resultMap;
	}

	class Ids {
		private String keyName;
		private String id;

		public String getKeyName() {
			return keyName;
		}

		public void setKeyName(String keyName) {
			this.keyName = keyName;
		}

		public String getId() {
			return id;
		}

		public void setId(String id) {
			this.id = id;
		}

		public Ids(String keyName, String id) {
			this.keyName = keyName;
			this.id = id;
		}
	}

	@Override
	public int updateSql(String srcConnectionParams, String sql) throws SQLException {
		Connection conn = DriverManager.getConnection(srcConnectionParams);
		Statement statement = conn.createStatement();
		int delCount = statement.executeUpdate(sql);
		return delCount;
	}
}
